package com.jplus.framework;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jplus.framework.bean.BeanHandle;
import com.jplus.framework.core.ClassScanner;
import com.jplus.framework.core.ConfigHandle;
import com.jplus.framework.core.classscan.DefaultClassScanner;
import com.jplus.framework.db.DataSourceFactory;
import com.jplus.framework.util.ClassUtil;
import com.jplus.framework.util.FormatUtil;

/**
 * 单例工厂<br>
 * 黄勇老师的单例工厂配置灵活性非常高，我将其弱化了
 * 
 * @author huangyong
 * @author Yuanqy
 */
public class InstanceFactory {
	private static final Logger logger = LoggerFactory.getLogger(InstanceFactory.class);
	/**
	 * 用于缓存对应的实例
	 */
	private static final Map<String, Object> cache = new ConcurrentHashMap<String, Object>();
	public static final String DS_FACTORY = "app.custom.db_plugin";

	/**
	 * 获取 ClassScanner
	 */
	public static ClassScanner getClassScanner() {
		return getInstance("app.custom.class_scanner", DefaultClassScanner.class);
	}

	/**
	 * 获取 DataSourceFactory
	 */
	public static DataSourceFactory getDataSourceFactory() {
		return getInstance(DS_FACTORY, null);
	}

	@SuppressWarnings("unchecked")
	public static <T> T getInstance(String cacheKey, Class<T> defaultImplClass) {
		if (cache.containsKey(cacheKey)) {
			return (T) cache.get(cacheKey);
		}
		String implClassName = ConfigHandle.getString(cacheKey,"");
		if (FormatUtil.isEmpty(implClassName)) {
			implClassName = defaultImplClass.getName();
		}
		Object instance = BeanHandle.getBean(ClassUtil.loadClass(implClassName));
		if (instance != null)
			cache.put(cacheKey, instance);
		else
			return newInstance(implClassName);
		return (T) instance;
	}

	/**
	 * 通过反射创建实例<br>
	 */
	@SuppressWarnings("unchecked")
	public static <T> T newInstance(String className) {
		T instance;
		try {
			logger.debug("#手动创建实例，并非容器：{}", className);
			Class<?> commandClass = ClassUtil.loadClass(className);
			instance = (T) commandClass.newInstance();
		} catch (Exception e) {
			logger.error("创建实例出错！", e);
			throw new RuntimeException(e);
		}
		return instance;
	}

}
